<template>
    <div class="graph-base_wrapper">
        <div class="dagre-header-wrap">
            <h3>graphlib基本用法</h3>
            <p class="redirect-field">
                <span :class="[
                    'field-item',
                    { 'active': dirIndex === index }
                ]"  
                v-for="(item, index) in layoutRedirect" 
                :key="index" 
                @click="onSelectDir(item, index)">{{ item.name }}</span>
            </p>
        </div>
        <div class="custom-graph-mind-wrap" id="graphcontainer"></div>
    </div>
</template>

<script setup>
// dagrejs中默认包含graphlib的
import dagre from "@dagrejs/dagre";
import { initDagreTree, renderView } from "./toolkit";
import svgPanZoom from 'svg-pan-zoom';
import { useWindowSize } from "@vueuse/core"

const { width: clientWidth, height }  = useWindowSize({})

const dirIndex = ref(0)
// 创建paper容器，渲染数据
const paper = ref(null)

// 创建图形容器
const graph = new dagre.graphlib.Graph({ directed: false, multigraph: true, compound: true })

// 布局方向
const layoutRedirect = ref([
    { name: '从上到下布局', value: 'TB' },
    { name: '从下到上布局', value: 'BT' },
    { name: '从左到右布局', value: 'LR' },
    { name: '从右到左布局', value: 'RL' },
])

const nodeList = ref([
    {id: 'kspacey', node: { label: "Kevin Spacey",  width: 144, height: 100 } },
    {id: 'swilliams', node: { label: "Saul Williams", width: 160, height: 100 } },
    {id: 'bpitt', node: { label: "Brad Pitt",     width: 108, height: 100 } },
    {id: 'lwilson', node: { label: "Luke Wilson",   width: 144, height: 100 } },
    {id: 'kbacon', node: { label: "Kevin Bacon",   width: 121, height: 100 }}
])
const edgeList = ref([
    { sourceId: 'kspacey', targetId: 'kbacon' },
    { sourceId: 'swilliams', targetId: 'kbacon' },
    { sourceId: 'bpitt', targetId: 'kbacon' },
    { sourceId: 'lwilson', targetId: 'kbacon' },
    { sourceId: 'lwilson', targetId: 'bpitt' },
])
const coordinateNodes = ref([])
const coordinateEdges = ref([])

watch( clientWidth, (n, o) => {
    // 窗口发生变化时，更新视图
    if (n) {
       
    }
})

// 初始化图形配置
function initGraph(params) {
    const containerDom = document.querySelector("#graphcontainer");
    const { clientWidth, clientHeight } = containerDom;
    
    // 配置图形setGraph对象设置属性
    graph.setGraph({
        rankdir: 'TB',
        width: clientWidth,
        height: clientHeight,
        align: 'UR',
        nodesep: 50, // 同层节点间距
        edgesep: 10, // 布局中水平分隔边缘的像素数
        ranksep: 60, // 层级间距
        marginx: 10,  // x 轴方向的边距
        marginy: 10,   // y 轴方向的边距
        ranker: 'network-simplex'
    })
    // 默认为每个新边分配一个新对象作为标签。
    graph.setDefaultEdgeLabel(function() { return {}})
    // 添加节点到图形容器，第一个参数是节点ID，
    // 第二个有关节点的元数据，此处为每个节点添加标签
    // 配置节点
    nodeList.value.forEach(el => graph.setNode(el.id, el.node))
    // 配置边
    edgeList.value.forEach(el => graph.setEdge(el.sourceId, el.targetId))
    console.log('1.Graph图形化和组装数据完成');
}

// 初始化树
const initRaphael = (rankdirType="TB") => {
    updateLayout(rankdirType)

    // 打印节点和边数据
    // console.log(coordinateNodes.value, coordinateEdges.value);

    // paper容器赋值，用于放置图形元素
    paper.value = initDagreTree({ containerId: "graphcontainer", connector:'curve', nodes: coordinateNodes.value, links: coordinateEdges.value, graph })
    console.log('2.Raphael渲染数据到Dom完成');
}

// 初始化svgPanZoom实例，用于移动和缩放svg
const initSvgPanZoom = () => {
    const svgElement = document.querySelector('#graphcontainer > svg')
    const panZoomTiger = svgPanZoom(svgElement, {
        viewportSelector: '#graphcontainer > svg',
        panEnabled: true, // 启用拖拽
        zoomEnabled: true, // 开启缩放
        controlIconsEnabled: true, // 开启图标控制，点击图标缩放
        dblClickZoomEnabled: false, // 禁止双击鼠标进行缩放视图
        mouseWheelZoomEnabled: true, // 开启鼠标滚轮缩放视图
        zoomScaleSensitivity: 0.2, // 变焦灵敏度 (Default 0.2)
        minZoom: 0.5, // 最小缩放级别 (Default 0.5)
        maxZoom: 10, // 最大缩放级别  (Default 10)
        fit: true, // 启用或禁用 SVG 中的视口适配
        center: true, // 在 SVG 中启用或禁用视口居中
    })
}

// 更新布局模式，重新计算节点和连线坐标
function updateLayout(rankdirType) {
    coordinateNodes.value = []
    coordinateEdges.value = []
    // 重置图形布局方向
    graph.setGraph({ rankdir: rankdirType })
    // 让dagre为这些节点和边做布局
    // layout图形将使用布局信息进行更新，节点node获得节点中心坐标x和y
    // 边edge获取一个points属性，该属性包括边的控制点坐标以及边与节点相交处的点
    // 边edge中此弯曲中心的x坐标和y坐标
    dagre.layout(graph)
    
    graph.nodes().forEach(function(v) {
        coordinateNodes.value.push(graph.node(v))
        // console.log("Node " + v + ": " + JSON.stringify(graph.node(v)));
    });

    graph.edges().forEach(function(e) {
        coordinateEdges.value.push(graph.edge(e))
        // console.log("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(graph.edge(e)));
    });
}

nextTick(() => {
    initGraph()
    initRaphael()
    initSvgPanZoom()
})

// 切换方向
function onSelectDir(item, index) {
    dirIndex.value = index
    // 清除画布内容，但svg保留
    paper.value.clear()
    updateLayout(item.value)
    renderView(coordinateNodes.value, coordinateEdges.value, 'curve')
}

</script>
<style lang="scss" src="./style.scss"></style>
